/*
 * Portions copyright 2004, the OpenGLUT project contributors.
 * OpenGLUT branched from freeglut in February, 2004.
 *
 * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
 * Written by Pawel W. Olszta, <olszta@sourceforge.net>
 * Creation date: Fri Dec 24 1999
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * Original teapot code copyright follows:
 */

/*
 * (c) Copyright 1993, Silicon Graphics, Inc.
 *
 * ALL RIGHTS RESERVED
 *
 * Permission to use, copy, modify, and distribute this software
 * for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that
 * both the copyright notice and this permission notice appear in
 * supporting documentation, and that the name of Silicon
 * Graphics, Inc. not be used in advertising or publicity
 * pertaining to distribution of the software without specific,
 * written prior permission.
 *
 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
 * "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
 * OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  IN NO
 * EVENT SHALL SILICON GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE
 * ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
 * INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
 * SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
 * NOT SILICON GRAPHICS, INC.  HAS BEEN ADVISED OF THE POSSIBILITY
 * OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * US Government Users Restricted Rights
 *
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
 * (c)(1)(ii) of the Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 and/or in similar or
 * successor clauses in the FAR or the DOD or NASA FAR
 * Supplement.  Unpublished-- rights reserved under the copyright
 * laws of the United States.  Contractor/manufacturer is Silicon
 * Graphics, Inc., 2011 N.  Shoreline Blvd., Mountain View, CA
 * 94039-7311.
 *
 * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
 */

#include <GL/glew.h>


/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */

/*
 * Rim, body, lid, and bottom data must be reflected in x and y;
 * handle and spout data across the y axis only.
 */
static int patchdata[][16] =
{
	{ 102, 103, 104, 105,   4,   5,   6,   7,
	8,   9,  10,  11,  12,  13,  14,  15 }, /* rim    */
	{  12,  13,  14,  15,  16,  17,  18,  19,
	20,  21,  22,  23,  24,  25,  26,  27 }, /* body   */
	{  24,  25,  26,  27,  29,  30,  31,  32,
	33,  34,  35,  36,  37,  38,  39,  40 },
	{  96,  96,  96,  96,  97,  98,  99, 100,
	101, 101, 101, 101,   0,   1,   2,   3 }, /* lid    */
	{   0,   1,   2,   3, 106, 107, 108, 109,
	110, 111, 112, 113, 114, 115, 116, 117 },
	{ 118, 118, 118, 118, 124, 122, 119, 121,
	123, 126, 125, 120,  40,  39,  38,  37 }, /* bottom */
	{  41,  42,  43,  44,  45,  46,  47,  48,
	49,  50,  51,  52,  53,  54,  55,  56 }, /* handle */
	{  53,  54,  55,  56,  57,  58,  59,  60,
	61,  62,  63,  64,  28,  65,  66,  67 },
	{  68,  69,  70,  71,  72,  73,  74,  75,
	76,  77,  78,  79,  80,  81,  82,  83 }, /* spout  */
	{  80,  81,  82,  83,  84,  85,  86,  87,
	88,  89,  90,  91,  92,  93,  94,  95 }
};

static double cpdata[][3] =
{
	{ 0.2,     0,      2.7    }, { 0.2,    -0.112,  2.7    },
	{ 0.112,  -0.2,    2.7    }, { 0,      -0.2,    2.7    },
	{ 1.3375,  0,      2.53125}, { 1.3375, -0.749,  2.53125},
	{ 0.749,  -1.3375, 2.53125}, { 0,      -1.3375, 2.53125},
	{ 1.4375,  0,      2.53125}, { 1.4375, -0.805,  2.53125},
	{ 0.805,  -1.4375, 2.53125}, { 0,      -1.4375, 2.53125},
	{ 1.5,     0,      2.4    }, { 1.5,    -0.84,   2.4    },
	{ 0.84,   -1.5,    2.4    }, { 0,      -1.5,    2.4    },
	{ 1.75,    0,      1.875  }, { 1.75,   -0.98,   1.875  },
	{ 0.98,   -1.75,   1.875  }, { 0,      -1.75,   1.875  },
	{ 2,       0,      1.35   }, { 2,      -1.12,   1.35   },
	{ 1.12,   -2,      1.35   }, { 0,      -2,      1.35   },
	{ 2,       0,      0.9    }, { 2,      -1.12,   0.9    },
	{ 1.12,   -2,      0.9    }, { 0,      -2,      0.9    },
	{-2,       0,      0.9    }, { 2,       0,      0.45   },
	{ 2,      -1.12,   0.45   }, { 1.12,   -2,      0.45   },
	{ 0,      -2,      0.45   }, { 1.5,     0,      0.225  },
	{ 1.5,    -0.84,   0.225  }, { 0.84,   -1.5,    0.225  },
	{ 0,      -1.5,    0.225  }, { 1.5,     0,      0.15   },
	{ 1.5,    -0.84,   0.15   }, { 0.84,   -1.5,    0.15   },
	{ 0,      -1.5,    0.15   }, {-1.6,     0,      2.025  },
	{-1.6,    -0.3,    2.025  }, {-1.5,    -0.3,    2.25   },
	{-1.5,     0,      2.25   }, {-2.3,     0,      2.025  },
	{-2.3,    -0.3,    2.025  }, {-2.5,    -0.3,    2.25   },
	{-2.5,     0,      2.25   }, {-2.7,     0,      2.025  },
	{-2.7,    -0.3,    2.025  }, {-3,      -0.3,    2.25   },
	{-3,       0,      2.25   }, {-2.7,     0,      1.8    },
	{-2.7,    -0.3,    1.8    }, {-3,      -0.3,    1.8    },
	{-3,       0,      1.8    }, {-2.7,     0,      1.575  },
	{-2.7,    -0.3,    1.575  }, {-3,      -0.3,    1.35   },
	{-3,       0,      1.35   }, {-2.5,     0,      1.125  },
	{-2.5,    -0.3,    1.125  }, {-2.65,   -0.3,    0.9375 },
	{-2.65,    0,      0.9375 }, {-2,      -0.3,    0.9    },
	{-1.9,    -0.3,    0.6    }, {-1.9,     0,      0.6    },
	{ 1.7,     0,      1.425  }, { 1.7,    -0.66,   1.425  },
	{ 1.7,    -0.66,   0.6    }, { 1.7,     0,      0.6    },
	{ 2.6,     0,      1.425  }, { 2.6,    -0.66,   1.425  },
	{ 3.1,    -0.66,   0.825  }, { 3.1,     0,      0.825  },
	{ 2.3,     0,      2.1    }, { 2.3,    -0.25,   2.1    },
	{ 2.4,    -0.25,   2.025  }, { 2.4,     0,      2.025  },
	{ 2.7,     0,      2.4    }, { 2.7,    -0.25,   2.4    },
	{ 3.3,    -0.25,   2.4    }, { 3.3,     0,      2.4    },
	{ 2.8,     0,      2.475  }, { 2.8,    -0.25,   2.475  },
	{ 3.525,  -0.25,   2.49375}, { 3.525,   0,      2.49375},
	{ 2.9,     0,      2.475  }, { 2.9,    -0.15,   2.475  },
	{ 3.45,   -0.15,   2.5125 }, { 3.45,    0,      2.5125 },
	{ 2.8,     0,      2.4    }, { 2.8,    -0.15,   2.4    },
	{ 3.2,    -0.15,   2.4    }, { 3.2,     0,      2.4    },
	{ 0,       0,      3.15   }, { 0.8,     0,      3.15   },
	{ 0.8,    -0.45,   3.15   }, { 0.45,   -0.8,    3.15   },
	{ 0,      -0.8,    3.15   }, { 0,       0,      2.85   },
	{ 1.4,     0,      2.4    }, { 1.4,    -0.784,  2.4    },
	{ 0.784,  -1.4,    2.4    }, { 0,      -1.4,    2.4    },
	{ 0.4,     0,      2.55   }, { 0.4,    -0.224,  2.55   },
	{ 0.224,  -0.4,    2.55   }, { 0,      -0.4,    2.55   },
	{ 1.3,     0,      2.55   }, { 1.3,    -0.728,  2.55   },
	{ 0.728,  -1.3,    2.55   }, { 0,      -1.3,    2.55   },
	{ 1.3,     0,      2.4    }, { 1.3,    -0.728,  2.4    },
	{ 0.728,  -1.3,    2.4    }, { 0,      -1.3,    2.4    },
	{ 0,       0,      0      }, { 1.425,  -0.798,  0      },
	{ 1.5,     0,      0.075  }, { 1.425,   0,      0      },
	{ 0.798,  -1.425,  0      }, { 0,      -1.5,    0.075  },
	{ 0,      -1.425,  0      }, { 1.5,    -0.84,   0.075  },
	{ 0.84,   -1.5,    0.075  }
};

static double tex[2][2][2] =
{
	{ {0.0, 0.0}, {1.0, 0.0} },
	{ {0.0, 1.0}, {1.0, 1.0} }
};

static void teapot( GLint grid, GLdouble scale, GLenum type )
{
	double p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
	long i, j, k, l;

	glPushAttrib( GL_ENABLE_BIT | GL_EVAL_BIT );
	glEnable( GL_AUTO_NORMAL );
	glEnable( GL_NORMALIZE );
	glEnable( GL_MAP2_VERTEX_3 );
	glEnable( GL_MAP2_TEXTURE_COORD_2 );

//	glPushMatrix();
	/* Need this to put top of the teapot towards +Z */
//	glRotated(270.0, 1.0, 0.0, 0.0);
//	glScaled(0.5 * scale, 0.5 * scale, 0.5 * scale);
//	glTranslated(0.0, 0.0, -1.5);

	for( i = 0; i < 10; i++ )
	{
		for( j = 0; j < 4; j++ )
			for( k = 0; k < 4; k++ )
				for( l = 0; l < 3; l++ )
		{
			p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
			q[j][k][l] = cpdata[patchdata[i][j * 4 + ( 3 - k )]][l];
			if( l == 1 )
				q[j][k][l] *= -1.0;
			if( i < 6 )
			{
				r[j][k][l] =
						cpdata[patchdata[i][j * 4 + ( 3 - k )]][l];
				if( l == 0 )
					r[j][k][l] *= -1.0;
				s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
				if( l == 0 )
					s[j][k][l] *= -1.0;
				if( l == 1 )
					s[j][k][l] *= -1.0;
			}
		}

		glMap2d(GL_MAP2_TEXTURE_COORD_2, 0.0, 1.0, 2, 2, 0.0, 1.0, 4, 2,
				&tex[0][0][0]);
		glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
				&p[0][0][0]);
		glMapGrid2d(grid, 1.0, 0.0, grid, 0.0, 1.0);
		glEvalMesh2(type, 0, grid, 0, grid);
		glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
				&q[0][0][0]);
		glEvalMesh2(type, 0, grid, 0, grid);
		if( i < 6 )
		{
			glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
					&r[0][0][0]);
			glEvalMesh2(type, 0, grid, 0, grid);
			glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
					&s[0][0][0]);
			glEvalMesh2(type, 0, grid, 0, grid);
		}
	}

//	glPopMatrix();
	glPopAttrib();
}


/* -- INTERFACE FUNCTIONS -------------------------------------------------- */

void drawTeapot()
{
	teapot( 14, 1.0f, GL_FILL );
}
